package com.gitee.alpha.ie.handler;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import com.google.common.collect.Maps;
import java.util.List;
import java.util.Map;
import org.apache.poi.ss.usermodel.Cell;

/**
 * 自定义列宽度自适应<br>
 *
 * @author 冰羽
 * @version 2.2.0
 */
public class CellWidthHandler extends AbstractColumnWidthStyleStrategy {
  private Map<Integer, Map<Integer, Integer>> cache = Maps.newHashMap();

  @Override
  protected void setColumnWidth(
      WriteSheetHolder writeSheetHolder,
      List<CellData> cellDataList,
      Cell cell,
      Head head,
      Integer relativeRowIndex,
      Boolean isHead) {
    boolean needSetWidth = isHead || CollectionUtil.isNotEmpty(cellDataList);
    if (needSetWidth) {
      Map<Integer, Integer> maxColumnWidthMap = cache.get(writeSheetHolder.getSheetNo());
      if (maxColumnWidthMap == null) {
        maxColumnWidthMap = Maps.newHashMap();
        cache.put(writeSheetHolder.getSheetNo(), maxColumnWidthMap);
      }

      int columnWidth = this.dataLength(cellDataList, cell, isHead);
      if (columnWidth >= 0) {
        if (columnWidth > 255) {
          columnWidth = 255;
        }

        Integer maxColumnWidth = maxColumnWidthMap.get(cell.getColumnIndex());
        if (maxColumnWidth == null || columnWidth > maxColumnWidth) {
          maxColumnWidthMap.put(cell.getColumnIndex(), columnWidth);
          writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), columnWidth * 256);
        }
      }
    }
  }

  private int dataLength(List<CellData> cellDataList, Cell cell, Boolean isHead) {
    if (isHead) {
      return cell.getStringCellValue().getBytes().length;
    } else {
      CellData cellData = cellDataList.get(0);
      CellDataTypeEnum type = cellData.getType();
      if (type == null) {
        return -1;
      } else {
        switch (type) {
          case STRING:
            return cellData.getStringValue().getBytes().length;
          case BOOLEAN:
            return cellData.getBooleanValue().toString().getBytes().length;
          case NUMBER:
            return cellData.getNumberValue().toString().getBytes().length;
          default:
            return -1;
        }
      }
    }
  }
}
